package com.dms.modules.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.dms.modules.product.dto.ProductDTO;
import com.dms.modules.product.dto.ProductSearchDTO;
import com.dms.modules.product.dto.ProductSkuDTO;
import com.dms.modules.product.entity.Product;
import com.dms.modules.product.entity.ProductFavorite;
import com.dms.modules.product.entity.ProductSku;
import com.dms.modules.product.entity.ProductCategory;
import com.dms.modules.product.mapper.ProductMapper;
import com.dms.modules.product.service.ProductCategoryService;
import com.dms.modules.product.service.ProductRecommendationService;
import com.dms.modules.product.service.ProductService;
import com.dms.modules.product.service.ProductFacade;
import com.dms.modules.product.service.ProductSkuService;
import com.dms.modules.product.vo.ProductDetailVO;
import com.dms.modules.user.entity.UserBrowseHistory;
import com.dms.modules.user.service.UserBehaviorService;
import com.dms.modules.merchant.entity.Merchant;
import com.dms.modules.merchant.service.MerchantService;
import com.dms.common.security.SecurityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.apache.commons.lang3.StringUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import com.dms.modules.product.service.ProductRecommendationFacade;
import com.dms.common.exception.BusinessException;
import com.dms.modules.message.enums.BusinessMessageType;
import com.fasterxml.jackson.databind.JsonNode;
import com.dms.modules.product.vo.ProductSpecVO;
import com.dms.modules.product.vo.ProductSkuVO;

import java.util.List;
import java.util.stream.Collectors;
import java.util.Map;
import java.util.Set;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Collections;
import java.math.BigDecimal;
import java.util.concurrent.TimeUnit;
import java.util.Arrays;

/**
 * 商品服务实现类
 */
@Slf4j
@Service
public class ProductServiceImpl extends BaseProductServiceImpl<ProductMapper, Product> implements ProductService {

    private static final String PRODUCT_CACHE_KEY = "product:detail:";
    private static final String PRODUCT_SEARCH_CACHE_KEY = "product:search:";
    private static final String PRODUCT_HOT_CACHE_KEY = "product:hot:";
    private static final String PRODUCT_NEW_CACHE_KEY = "product:new:";
    
    @Autowired
    @Lazy
    private ProductFacade productFacade;
    
    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    @Lazy
    private UserBehaviorService userBehaviorService;

    @Autowired
    private ProductCategoryService productCategoryService;

    @Autowired
    private ProductRecommendationService productRecommendationService;

    @Autowired
    private ProductRecommendationFacade recommendationFacade;

    @Autowired
    @Lazy
    private MerchantService merchantService;

    @Autowired
    @Lazy
    private ProductSkuService productSkuService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createProduct(ProductDTO productDTO) {
        Product product = new Product();
        BeanUtils.copyProperties(productDTO, product);
        
        // 设置商家ID
        Long userId = SecurityUtils.getCurrentUserId();
        if (userId == null) {
            throw new BusinessException("未获取到用户信息");
        }
        
        // 获取商家信息
        Merchant merchant = merchantService.getOne(new LambdaQueryWrapper<Merchant>()
                .eq(Merchant::getUserId, userId));
        if (merchant == null) {
            throw new BusinessException("未获取到商家信息");
        }
        product.setMerchantId(merchant.getId());
        
        // 处理商品子图
        if (productDTO.getSubImages() != null && !productDTO.getSubImages().isEmpty()) {
            product.setSubImages(String.join(",", productDTO.getSubImages()));
        }
        
        // 处理规格相关的价格和库存
        if (!productDTO.getHasSpecs()) {
            // 无规格商品，直接设置价格和库存
            product.setPrice(productDTO.getSinglePrice());
            product.setStock(productDTO.getSingleStock());
            product.setSpecs("[]"); // 空规格数组
        } else {
            // 多规格商品，初始化价格和库存为0，等待SKU创建后更新
            product.setPrice(BigDecimal.ZERO);
            product.setStock(0);
            
            // 验证规格信息
            if (StringUtils.isBlank(productDTO.getSpecs())) {
                throw new BusinessException("多规格商品必须设置规格信息");
            }
            try {
                JsonNode specsNode = objectMapper.readTree(productDTO.getSpecs());
                if (!specsNode.isArray()) {
                    throw new BusinessException("商品规格格式错误，应为JSON数组");
                }
            } catch (Exception e) {
                log.error("解析商品规格JSON失败", e);
                throw new BusinessException("商品规格格式错误");
            }
        }
        
        // 设置初始值
        product.setSales(0);
        product.setViewCount(0);
        product.setAuditStatus(1); // 默认审核通过
        
        // 保存商品
        save(product);

        // 创建SKU
        if (!productDTO.getHasSpecs()) {
            // 创建默认SKU
            ProductSkuDTO defaultSku = new ProductSkuDTO();
            defaultSku.setProductId(product.getId());
            defaultSku.setSkuName(product.getName());
            defaultSku.setPrice(productDTO.getSinglePrice());
            defaultSku.setStock(productDTO.getSingleStock());
            defaultSku.setSpecValues("{}"); // 空规格对象
            defaultSku.setStatus(1);
            defaultSku.setMerchantId(merchant.getId());
            
            boolean success = productSkuService.create(defaultSku);
            if (!success) {
                throw new BusinessException("创建默认SKU失败");
            }
        }
        
        return product.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateProduct(ProductDTO productDTO) {
        Product product = getById(productDTO.getId());
        if (product == null) {
            throw new BusinessException("商品不存在");
        }
        
        // 验证商家权限
        Long userId = SecurityUtils.getCurrentUserId();
        if (userId == null) {
            throw new BusinessException("未获取到用户信息");
        }
        
        Merchant merchant = merchantService.getOne(new LambdaQueryWrapper<Merchant>()
                .eq(Merchant::getUserId, userId));
        if (merchant == null || !product.getMerchantId().equals(merchant.getId())) {
            throw new BusinessException("无权修改该商品");
        }
        
        BeanUtils.copyProperties(productDTO, product);
        
        // 处理商品子图
        if (productDTO.getSubImages() != null && !productDTO.getSubImages().isEmpty()) {
            product.setSubImages(String.join(",", productDTO.getSubImages()));
        }
        
        return updateById(product);
    }

    @Override
    public ProductDetailVO getProductDetail(Long id) {
        Product product = getById(id);
        if (product == null) {
            throw new BusinessException("商品不存在");
        }
        return convertToProductDetailVO(product);
    }

    @Override
    public IPage<Product> getProductsByMerchant(Long merchantId, Integer pageNum, Integer pageSize) {
        Page<Product> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<Product> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Product::getMerchantId, merchantId)
               .eq(Product::getDeleted, 0)
               .orderByDesc(Product::getCreateTime);
        return page(page, wrapper);
    }

    @Override
    public IPage<Product> search(ProductSearchDTO search) {
        Page<Product> page = new Page<>(search.getPageNum(), search.getPageSize());
        LambdaQueryWrapper<Product> wrapper = new LambdaQueryWrapper<>();

        // 关键字模糊查询
        if (org.apache.commons.lang3.StringUtils.isNotBlank(search.getKeyword())) {
            wrapper.and(w -> w.like(Product::getName, search.getKeyword())
                              .or().like(Product::getSubtitle, search.getKeyword())
                              .or().like(Product::getDetail, search.getKeyword()));
        }
        if (search.getCategoryId() != null) {
            wrapper.eq(Product::getCategoryId, search.getCategoryId());
        }
        if (search.getMinPrice() != null) {
            wrapper.ge(Product::getPrice, search.getMinPrice());
        }
        if (search.getMaxPrice() != null) {
            wrapper.le(Product::getPrice, search.getMaxPrice());
        }
        // 其他条件可按需补充
        wrapper.eq(Product::getDeleted, 0);

        return this.page(page, wrapper);
    }

    @Override
    public IPage<Product> searchMerchantProducts(ProductSearchDTO search, Integer status) {
        search.setStatus(status);
        return searchProducts(search, SearchType.MERCHANT);
    }

    @Override
    public IPage<Product> adminSearchProducts(ProductSearchDTO search, Integer auditStatus) {
        search.setAuditStatus(auditStatus);
        return searchProducts(search, SearchType.ADMIN);
    }

    /**
     * 统一的商品搜索方法
     */
    private IPage<Product> searchProducts(ProductSearchDTO search, SearchType type) {
        String cacheKey = PRODUCT_SEARCH_CACHE_KEY + type.name() + ":" + search.hashCode();
        IPage<Product> cachedResult = (IPage<Product>) redisTemplate.opsForValue().get(cacheKey);
        if (cachedResult != null) {
            return cachedResult;
        }
        
        Page<Product> page = new Page<>(search.getPageNum(), search.getPageSize());
        Map<String, Object> conditions = new HashMap<>();
        
        // 设置查询条件
        if (StringUtils.isNotBlank(search.getKeyword())) {
            conditions.put("name", search.getKeyword());
            conditions.put("subtitle", search.getKeyword());
        }
        if (search.getCategoryId() != null) {
            conditions.put("categoryId", search.getCategoryId());
        }
        if (search.getMerchantId() != null) {
            conditions.put("merchantId", search.getMerchantId());
        }
        if (search.getMinPrice() != null) {
            conditions.put("minPrice", search.getMinPrice());
        }
        if (search.getMaxPrice() != null) {
            conditions.put("maxPrice", search.getMaxPrice());
        }
        if (search.getStatus() != null) {
            conditions.put("status", search.getStatus());
        }
        if (search.getAuditStatus() != null) {
            conditions.put("auditStatus", search.getAuditStatus());
        }
        
        IPage<Product> result = page(page, conditions);
        redisTemplate.opsForValue().set(cacheKey, result, CACHE_EXPIRE_HOURS, TimeUnit.HOURS);
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteProduct(Long id) {
        return productFacade.deleteProductWithSkus(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateProductStatus(Long id, ProductStatusType type, Boolean value) {
        Product product = getById(id);
        if (product == null) {
            throw new BusinessException("商品不存在");
        }

        // 如果是商家修改上下架状态，需要检查审核状态
        if (type == ProductStatusType.STATUS) {
            if (product.getAuditStatus() == 2) {
                throw new BusinessException("商品已被禁用，无法修改状态");
            }
        }

        SFunction<Product, Integer> statusField;
        Integer statusValue;
        
        switch (type) {
            case STATUS:
                statusField = Product::getStatus;
                statusValue = value ? 1 : 0;
                break;
            case RECOMMEND:
                statusField = Product::getIsRecommend;
                statusValue = value ? 1 : 0;
                break;
            case NEW:
                statusField = Product::getIsNew;
                statusValue = value ? 1 : 0;
                break;
            case HOT:
                statusField = Product::getIsHot;
                statusValue = value ? 1 : 0;
                break;
            case AUDIT:
                statusField = Product::getAuditStatus;
                statusValue = value ? 1 : 2; // true = 通过(1), false = 禁用(2)
                break;
            default:
                throw new BusinessException("不支持的状态类型");
        }
        
        boolean result = updateStatus(id, statusField, statusValue);
        if (result) {
            product = getById(id);
            if (product != null) {
                updateCache(id, product, PRODUCT_CACHE_KEY);
                
                // 如果是管理员设置审核状态为禁用，同时下架商品
                if (type == ProductStatusType.AUDIT && !value) {
                    updateStatus(id, Product::getStatus, 0);
                }
            }
        }
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateStock(Long id, Integer stock) {
        checkExists(id, "商品不存在");
        boolean result = lambdaUpdate()
                .set(Product::getStock, stock)
                .eq(Product::getId, id)
                .update();
        if (result) {
            Product product = getById(id);
            if (product != null) {
                updateCache(id, product, PRODUCT_CACHE_KEY);
            }
        }
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean incrementViewCount(Long id) {
        checkExists(id, "商品不存在");
        boolean result = lambdaUpdate()
                .setSql("view_count = view_count + 1")
                .eq(Product::getId, id)
                .update();
        if (result) {
            Product product = getById(id);
            if (product != null) {
                updateCache(id, product, PRODUCT_CACHE_KEY);
            }
        }
        return result;
    }

    @Override
    public List<ProductDetailVO> getHotProducts(Integer limit) {
        return productRecommendationService.getHotProducts(limit);
    }

    @Override
    public List<ProductDetailVO> getNewProducts(Integer limit) {
        return productRecommendationService.getNewProducts(limit);
    }

    @Override
    public List<String> getSearchSuggestions(String keyword, Integer limit) {
        // TODO: 实现搜索建议功能
        return Collections.emptyList();
    }

    @Override
    public List<String> getSearchHistory(Long userId, Integer limit) {
        // TODO: 实现搜索历史功能
        return Collections.emptyList();
    }

    @Override
    public void clearSearchHistory(Long userId) {
        // TODO: 实现清除搜索历史功能
    }

    @Override
    public IPage<Product> getAuditPendingProducts(Integer pageNum, Integer pageSize) {
        Page<Product> page = new Page<>(pageNum, pageSize);
        Map<String, Object> conditions = new HashMap<>();
        conditions.put("auditStatus", 0);
        return page(page, conditions);
    }

    @Override
    public List<ProductDetailVO> getProductDetails(List<Long> ids) {
        List<Product> products = listByIds(ids, PRODUCT_CACHE_KEY);
        return convertToProductDetailVO(products);
    }

    @Override
    public List<ProductDetailVO> convertToProductDetailVO(List<Product> products) {
        return products.stream()
                .map(this::convertToProductDetailVO)
                .collect(Collectors.toList());
    }

    /**
     * 将Product转换为ProductDetailVO
     */
    private ProductDetailVO convertToProductDetailVO(Product product) {
        if (product == null) {
            return null;
        }

        ProductDetailVO vo = new ProductDetailVO();
        BeanUtils.copyProperties(product, vo);

        // 设置分类信息
        if (product.getCategoryId() != null) {
            ProductCategory category = productCategoryService.getById(product.getCategoryId());
            if (category != null) {
                vo.setCategoryName(category.getName());
            }
        }

        // 设置商家信息
        if (product.getMerchantId() != null) {
            Merchant merchant = merchantService.getById(product.getMerchantId());
            if (merchant != null) {
                vo.setMerchantName(merchant.getShopName());
            }
        }

        // 设置SKU信息
        List<ProductSku> skuList = productFacade.getProductSkus(product.getId());
        vo.setSkuList(skuList);

        // 处理商品子图
        if (StringUtils.isNotBlank(product.getSubImages())) {
            vo.setSubImages(Arrays.asList(product.getSubImages().split(",")));
        }

        return vo;
    }

    @Override
    @SuppressWarnings("unchecked")
    protected <R> SFunction<Product, R> getFieldFunction(String fieldName) {
        try {
            return (SFunction<Product, R>) Product.class.getDeclaredField(fieldName).get(null);
        } catch (Exception e) {
            log.warn("Failed to get field function for: {}", fieldName, e);
            return null;
        }
    }

    @Override
    protected SFunction<Product, Long> getIdField() {
        return Product::getId;
    }

    /**
     * 搜索类型枚举
     */
    private enum SearchType {
        NORMAL,
        MERCHANT,
        ADMIN
    }

    @Override
    public IPage<Product> getProducts(Integer pageNum, Integer pageSize, Long categoryId, 
                                    Boolean isNew, Boolean isHot, Boolean isRecommend) {
        Page<Product> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<Product> wrapper = new LambdaQueryWrapper<>();
        
        // 设置查询条件
        if (categoryId != null) {
            wrapper.eq(Product::getCategoryId, categoryId);
        }
        if (isNew != null) {
            wrapper.eq(Product::getIsNew, isNew ? 1 : 0);
        }
        if (isHot != null) {
            wrapper.eq(Product::getIsHot, isHot ? 1 : 0);
        }
        if (isRecommend != null) {
            wrapper.eq(Product::getIsRecommend, isRecommend ? 1 : 0);
        }
        
        // 只查询上架的商品
        wrapper.eq(Product::getStatus, 1);
        
        // 按创建时间倒序排序
        wrapper.orderByDesc(Product::getCreateTime);
        
        return page(page, wrapper);
    }

    private BusinessMessageType getMessageType(Integer status) {
        switch (status) {
            case 1:
                return BusinessMessageType.PRODUCT_ON_SHELF;
            case 2:
                return BusinessMessageType.PRODUCT_OFF_SHELF;
            case 3:
                return BusinessMessageType.PRODUCT_PRICE_CHANGE;
            case 4:
                return BusinessMessageType.PRODUCT_STOCK_LOW;
            default:
                return BusinessMessageType.PRODUCT_OFF_SHELF;
        }
    }

    @Override
    public Integer countByMerchantId(Long merchantId) {
        return Math.toIntExact(count(new LambdaQueryWrapper<Product>()
                .eq(Product::getMerchantId, merchantId)
                .eq(Product::getDeleted, 0)));
    }

    @Override
    public Integer countByMerchantIdAndStatus(Long merchantId, Integer status) {
        return Math.toIntExact(count(new LambdaQueryWrapper<Product>()
                .eq(Product::getMerchantId, merchantId)
                .eq(Product::getStatus, status)
                .eq(Product::getDeleted, 0)));
    }

    /**
     * 更新商品总库存（根据SKU库存总和）
     * @param productId 商品ID
     * @return 是否成功
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean updateTotalStock(Long productId) {
        // 获取商品所有SKU的库存总和
        List<ProductSku> skuList = productFacade.getProductSkus(productId);
        int totalStock = skuList.stream()
                .mapToInt(ProductSku::getStock)
                .sum();
        
        // 更新商品总库存
        return lambdaUpdate()
                .eq(Product::getId, productId)
                .set(Product::getStock, totalStock)
                .update();
    }

    @Override
    public List<ProductSpecVO> getProductSpecs(Long productId) {
        log.debug("Getting product specs for productId: {}", productId);
        
        Product product = getById(productId);
        if (product == null) {
            log.error("Product not found with id: {}", productId);
            throw new BusinessException("商品不存在");
        }

        List<ProductSpecVO> specsList = new ArrayList<>();
        String specs = product.getSpecs();
        
        log.debug("Raw specs data: [{}]", specs);
        
        if (specs != null) {
            try {
                JsonNode specsNode = objectMapper.readTree(specs);
                log.debug("Parsed specs node: {}", specsNode);
                
                if (specsNode.isArray()) {
                    for (JsonNode spec : specsNode) {
                        ProductSpecVO specVO = new ProductSpecVO();
                        
                        JsonNode nameNode = spec.get("name");
                        if (nameNode == null || nameNode.isNull()) {
                            log.warn("Spec name is missing or null, skipping spec: {}", spec);
                            continue;
                        }
                        specVO.setName(nameNode.asText());
                        
                        List<String> values = new ArrayList<>();
                        JsonNode valuesNode = spec.get("values");
                        if (valuesNode != null && valuesNode.isArray()) {
                            for (JsonNode value : valuesNode) {
                                if (!value.isNull()) {
                                    values.add(value.asText());
                                }
                            }
                        } else {
                            log.warn("Values node is missing or not an array for spec: {}", nameNode.asText());
                        }
                        
                        specVO.setValues(values);
                        specsList.add(specVO);
                        log.debug("Added spec: name={}, values={}", specVO.getName(), specVO.getValues());
                    }
                } else {
                    log.warn("Product specs is not an array: {}", specsNode);
                }
            } catch (Exception e) {
                log.error("Failed to parse product specs for productId {}: {}", productId, e.getMessage(), e);
            }
        } else {
            log.debug("Product specs is null");
        }
        
        log.debug("Returning {} specs for productId {}", specsList.size(), productId);
        return specsList;
    }

    @Override
    public List<ProductSkuVO> getProductSkus(Long productId) {
        log.debug("Getting product SKUs for productId: {}", productId);
        
        List<ProductSku> skuList = productFacade.getProductSkus(productId);
        if (skuList.isEmpty()) {
            log.warn("No SKUs found for productId: {}", productId);
            throw new BusinessException("商品暂无SKU信息");
        }

        List<ProductSkuVO> skuVOList = new ArrayList<>();
        
        for (ProductSku sku : skuList) {
            try {
                ProductSkuVO skuVO = new ProductSkuVO();
                skuVO.setId(sku.getId());
                
                if (sku.getSpecValues() != null && !sku.getSpecValues().trim().isEmpty()) {
                    try {
                        Map<String, String> specs = objectMapper.readValue(sku.getSpecValues(), Map.class);
                        skuVO.setSpecs(specs);
                        log.debug("Parsed SKU specs for skuId {}: {}", sku.getId(), specs);
                    } catch (Exception e) {
                        log.error("Failed to parse SKU spec values for skuId {}: {}", sku.getId(), e.getMessage(), e);
                        skuVO.setSpecs(new HashMap<>());
                    }
                } else {
                    log.debug("SKU {} has no spec values defined", sku.getId());
                    skuVO.setSpecs(new HashMap<>());
                }
                
                skuVO.setPrice(sku.getPrice());
                skuVO.setStock(sku.getStock());
                
                skuVOList.add(skuVO);
                log.debug("Added SKU: id={}, specs={}, price={}, stock={}", 
                    skuVO.getId(), skuVO.getSpecs(), skuVO.getPrice(), skuVO.getStock());
            } catch (Exception e) {
                log.error("Failed to process SKU with id {}: {}", sku.getId(), e.getMessage(), e);
            }
        }
        
        log.debug("Returning {} SKUs for productId {}", skuVOList.size(), productId);
        return skuVOList;
    }
}